package com.ceair.flight.refund.service.notification.impl;

import com.alibaba.fastjson.JSON;
import com.ceair.flight.refund.dto.external.RefundApply;
import com.ceair.flight.refund.dto.external.RefundSeg;
import com.ceair.flight.refund.dto.external.RefundTkt;
import com.ceair.flight.refund.location.dt.enums.ModuleConstants;
import com.ceair.flight.refund.location.dt.enums.RefundNotifyType;
import com.ceair.flight.refund.service.mailAndSms.MailAndSMSMessageProducer;
import com.ceair.flight.refund.service.notification.INotification;
import com.ceair.muservice.basicdata.dto.airport.AirportDto;
import com.ceair.muservice.basicdata.dto.channel.ChannelManageDto;
import com.ceair.muservice.basicdata.feign.util.AirportUtil;
import com.ceair.muservice.basicdata.feign.util.ChannelUtil;
import com.ceair.muservice.common.dto.queue.MailAndSMSMessage;
import com.ceair.muservice.common.enums.message.TemplateNameEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class RefundSuccessNotification implements INotification {

    private static final Logger LOG = LoggerFactory.getLogger(RefundSuccessNotification.class);

    @Resource
    private MailAndSMSMessageProducer mailAndSMSMessageProducer;

    @Override
    public void notify4Apply(Map args) {
        try {
            if (args.get("REFUND_APPLY_ID") == null) {
                LOG.error("获得退票详细ID异常++++++++++");
                return;
            }
            /**
             * 退票订单详情 *
             */
            LOG.info(args.get("REFUND_APPLY_ID") + "获得退票详查询ID号");
            Object applyId = args.get(ModuleConstants.REFUND_APPLY_ID_KEY);
            Object refundApplyO = args.get(ModuleConstants.REFUND_APPLY_KEY);
            if (refundApplyO == null) {
                LOG.error("Refund apply not found");
                return;
            }
            RefundApply loadDetail = (RefundApply) refundApplyO;
            RefundTkt refundTkt = loadDetail.getRefundTkt();
            if (refundTkt == null) {
                LOG.error("Send notification failed for refund apply {} due to no refund ticket detail not found", applyId);
                return;
            }
            String channel = refundTkt.getChannelNo();
            LOG.debug("Refund ticket channel No is {}", channel);

            String notifyTypeCode = (String) args.get("NOTIFY_TYPE");
            RefundNotifyType notifyType = RefundNotifyType.getByCode(notifyTypeCode);
            if (null != notifyType) {
                switch (notifyType) {
                    case TEXT_MESSAGE:
                        /**
                         * 短信业务 *
                         */
                        /*smsAdvice(loadDetail, site, airportInfos);*/
                        break;
                    case EMAIL:
                        /**
                         * 邮箱业务 *
                         */
                        mailAdvice(loadDetail, channel);
                        break;
                    case SMS_EMAIL:
                        /**
                         * 短信 邮箱业务 *
                         */
                        mailAdvice(loadDetail, channel);
                        break;
                    default:
                        break;
                }
            }
        } catch (Exception ex) {
            LOG.error("发送退票通知异常", ex);
        }
    }


    private String getRefundNotifyEmails(RefundApply loadDetail) {
        String notifyEmails = "";
        String notifyMail = loadDetail.getContactEmail();
        notifyEmails = append(notifyEmails, notifyMail);
        notifyMail = loadDetail.getClaimerEmail();
        notifyEmails = append(notifyEmails, notifyMail);
        notifyMail = loadDetail.getRefundTkt().getPaxEmail();
        notifyEmails = append(notifyEmails, notifyMail);
        notifyEmails = notifyEmails.replaceAll(",", ";");
        LOG.info("Notification will send to below emails {}", notifyEmails);
        return notifyEmails;
    }

    private String append(String old, String needToAdd) {
        if (needToAdd != null && !needToAdd.isEmpty()) {
            final String lowerValue = needToAdd.toLowerCase();
            if (!old.contains(lowerValue)) {
                if (old.isEmpty()) {
                    old += lowerValue;
                } else {
                    old += ",";
                    old += lowerValue;
                }
            }
        }
        return old;
    }

    private Map<String, AirportDto> getAirportInfos(RefundTkt tkt) {
        LOG.info("进入获取三字码公共服务+++");
        Set<String> airportCodes = new HashSet<>();
        setAirportCodes(airportCodes, tkt);
        List<AirportDto> nationCityAirportDtoList = AirportUtil.findByCodeList(airportCodes.stream().collect(Collectors.toList()));
        Map<String, AirportDto> map = new HashMap<>(16);
        if (!CollectionUtils.isEmpty(nationCityAirportDtoList)) {
            nationCityAirportDtoList.stream().forEach(e -> map.put(e.getCode(), e));
        }
        return map;
    }

    private void setAirportCodes(Set<String> airportCodes, RefundTkt tkt) {
        Optional.ofNullable(tkt.getRefundSegs()).ifPresent(refundSegs -> refundSegs.stream().forEach(seg -> {
            airportCodes.add(seg.getArriveAirport());
            airportCodes.add(seg.getDepartAirport());
        }));
    }

    /**
     * @param loadDetail
     * @param channel
     */
    public void mailAdvice(RefundApply loadDetail, String channel) {
        ChannelManageDto channelManageDto = ChannelUtil.findChannelByChannelCode(channel);
        String site = channelManageDto.getLanguageCode();
        String[] siteSplit = site.split("_");
        String language = siteSplit[0];
        String country = siteSplit[siteSplit.length - 1];

        LOG.info("根据服务渠道号获取站点代码++++" + site);
        Map<String, AirportDto> airportInfos = getAirportInfos(loadDetail.getRefundTkt());
        try {
            MailAndSMSMessage mailMessage = new MailAndSMSMessage();
            LOG.info("退票邮件开始发送...");
            Map<String, Object> map = new HashMap<>();
            mailMessage.setMsgTP("MAIL");
            mailMessage.setServerTy(TemplateNameEnum.REFSUCCESS_MAIL.getCode());
            mailMessage.setChannel(channel);
            mailMessage.setCountry(country);
            mailMessage.setLanguage(language);
            map.put("site", language);
            /**
             * 邮箱 *
             */
            map.put("receiver", getRefundNotifyEmails(loadDetail));
            /**
             * 姓名 *
             */
            map.put("paxName", loadDetail.getClaimerName());
            final RefundTkt refundTkt = loadDetail.getRefundTkt();
            /**
             * 大订单号 *
             */
            map.put("ordNo", refundTkt.getOrderNo());
            /**
             * 币种 *
             */
            map.put("currency", loadDetail.getCurrency());

            boolean isVol = loadDetail.isVoluntary();
            if (isVol && loadDetail.getRefundAmount().compareTo(BigDecimal.ZERO) > 0) {
                /**
                 * 退票费,总手续费(所有航段上的手续费之和) *
                 */
                map.put("refundPrice", loadDetail.getRefundFee());
                /**
                 * 应退金额,总额 *
                 */
                map.put("totalAmount", loadDetail.getRefundAmount());
            }
            Long refundPoints = loadDetail.getRefundPoints();
            if (loadDetail.getPointsType() != null && refundPoints != null) {
                map.put("refundPoints", refundPoints);
            }

            /**
             * 退票航段集合 *
             */
            List<Map<String, Object>> segs = getSegsDetails(loadDetail, airportInfos, site);
            map.put("segs", segs);
            //乘客信息
            map.put("paxs", fillPaxDetail(loadDetail));
            mailMessage.setMap(map);
            /**
             * 邮件发送
             */
            mailAndSMSMessageProducer.sendMessage(mailMessage);
            LOG.info("退票邮件发送成功.mail:\n" + JSON.toJSONString(mailMessage));
        } catch (Exception e) {
            LOG.error("退票邮件发送失败！", e);
        }
    }

    private List fillPaxDetail(RefundApply refundApply) {
        RefundTkt tkt = refundApply.getRefundTkt();
        String ticketNo = tkt.getTicketNo();
        String paxName = tkt.getPaxName();
        String paxType = tkt.getPaxType();
        List<Map<String, Object>> passengers = new ArrayList<>(1);
        Map pax = new HashMap();
        pax.put("ticketNo", ticketNo);
        pax.put("paxType", paxType);
        pax.put("paxName", paxName);
        passengers.add(pax);
        return passengers;
    }

    private List<Map<String, Object>> getSegsDetails(RefundApply loadDetail, Map<String, AirportDto> airportInfos,String site) {
        /**
         * 退票航段集合 *
         */
        List<Map<String, Object>> segs = new ArrayList<>();
        final RefundTkt refundTkt = loadDetail.getRefundTkt();
        final Set<RefundSeg> refundSegs = refundTkt.getRefundSegs();
        List<RefundSeg> sortRefundSegs = new ArrayList<>(refundSegs);
        Collections.sort(sortRefundSegs);
        /**
         * 单个的航段信息 *
         */
        Map<String, Object> seg;
        SimpleDateFormat df = new SimpleDateFormat();
        for (RefundSeg refundSeg : sortRefundSegs) {
            seg = new HashMap<>();
            seg.put("flightNo", refundSeg.getFlightNo());
            final AirportDto departAirport = airportInfos.get(refundSeg.getDepartAirport());
            /**
             * 起飞城市 *
             */
            seg.put("orgCode", departAirport.getCity(site));
            /**
             * 起飞机场 *
             */
            seg.put("orgAirport", departAirport.getName(site));
            final AirportDto arrivalAirport = airportInfos.get(refundSeg.getArriveAirport());
            /**
             * 到达城市 *
             */
            seg.put("destCode", arrivalAirport.getCity(site));
            /**
             * 到达机场 *
             */
            seg.put("destAirport", arrivalAirport.getName(site));
            df.applyPattern("yyyy-MM-dd");
            seg.put("orgDate", df.format(refundSeg.getDepartDate()));
            seg.put("destDate", df.format(refundSeg.getArriveDate()));
            df.applyPattern("HH:mm");
            seg.put("orgTime", df.format(refundSeg.getDepartDate()));
            seg.put("destTime", df.format(refundSeg.getArriveDate()));
            /**
             * 航班类型 *
             */
            seg.put("flightType", refundSeg.getSegType());
            /**
             * 舱位 *
             */
            seg.put("cabinCode", refundSeg.getCabin());
            seg.put("e", refundSeg.getEiContent());
            segs.add(seg);
        }
        return segs;
    }

}
